package br.com.saab.quantotempofalta.negocio;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import br.com.saab.quantotempofalta.form.HorariosForm;
import br.com.saab.quantotempofalta.menu.item.AvisarMenu;
import br.com.saab.quantotempofalta.negocio.observer.ControladorHorasTrabalhadas;
import br.com.saab.quantotempofalta.negocio.observer.TerminaLogoDia;
import br.com.saab.quantotempofalta.negocio.observer.Terminooou;

/**
 * <p>
 * Classe responsável por saber quando já deu a hora de ir embora.
 * </p>
 * <p>
 * Implementa o design pattern Observer para avisar quando o horário foi
 * atualizado e quando já deu a hora de ir embora.
 * </p>
 * 
 * @author Felipe
 */
@Component
public class AtualizaHorasTrabalhadas implements Runnable, ControladorHorasTrabalhadas {

	private final long SLEEP_TIME = 1000;
	private final long SEGUNDO_AVISO = 7000; //1000 * 60 * 2; // dois minutos depois
	private final long TERCEIRO_AVISO = 15000; //1000 * 60 * 5; // cinco minutos depois
	private final String CARGA_HORARIA = "08h, 00m, 00s";

	private AvisarMenu avisarMenu;
	private HorariosForm horariosForm;
	private CalculadorHorasTrabalhadas calculador;
	private List<TerminaLogoDia> terminaLogoDiaListeners;
	private List<Terminooou> terminooouListeners;

	@Autowired
	public AtualizaHorasTrabalhadas(AvisarMenu avisarMenu, HorariosForm horariosForm, CalculadorHorasTrabalhadas calculador) {
		super();
		this.avisarMenu = avisarMenu;
		this.horariosForm = horariosForm;
		this.calculador = calculador;
		terminaLogoDiaListeners = new ArrayList<TerminaLogoDia>();
		terminooouListeners = new ArrayList<Terminooou>();
	}

	@Override
	public void run() {
		String horasTrabalhadas = "";
		String temp = "";
		int quantAvisos = -1;
		long tempoDesdeUltimoAviso = 0L;

		while (true) {
			// Se já acabou o dia árduo de trabalho...
			if (horasTrabalhadas.equals(CARGA_HORARIA)) {
				
				// Sinaliza o primeiro aviso
				if (quantAvisos == -1)
					quantAvisos = 0;
				
				// Avisa 3 vezes que o dia acabou e é hora de ir embora dormir ou beber
				if (quantAvisos == 0
						|| (quantAvisos == 1 && tempoDesdeUltimoAviso >= SEGUNDO_AVISO)
						|| (quantAvisos == 2 && tempoDesdeUltimoAviso >= TERCEIRO_AVISO)) {
				
					if (avisarMenu.precisaAvisar()) {
						for (Terminooou listener : terminooouListeners) 
							listener.finalmenteAcabouODia(quantAvisos);
					}
				
					// Avisou mais uma vez...
					quantAvisos++;
				}
				
				// Ai já deu né... 
				// Se depois de 3 avisos se o cara não for embora tem apanhar.. ¬¬
				if (quantAvisos == 3) {
					quantAvisos = -1;
					tempoDesdeUltimoAviso = 0L;
					horariosForm.setEntrada1("");
					horariosForm.setSaida1("");
					horariosForm.setEntrada2("");
					horariosForm.setSaida2("");
					horasTrabalhadas="";
				}
			} else {
				
				// Se ainda não acabou o dia então calcula quanto falta...
				calculador.setHoraEntrada1(horariosForm.getEntrada1());
				calculador.setHoraSaida1(horariosForm.getSaida1());
				calculador.setHoraEntrada2(horariosForm.getEntrada2());
				calculador.setHoraSaida2(horariosForm.getSaida2());
				temp = calculador.getHorasTrabalhadas();

				// Se mudou a quantidade de horas trabalhadas então avisa os observers
				if (horasTrabalhadas != temp) {
					horasTrabalhadas = temp;
	
					for (TerminaLogoDia listener : terminaLogoDiaListeners)
						listener.trabalheiMaisUmPouco(horasTrabalhadas);
				}
			}
			
			try {
				Thread.sleep(SLEEP_TIME);
				
				// Se já deu o horário guarda quanto tempo desde o último aviso
				// para poder avisar 3 vezes
				if (quantAvisos > -1)
					tempoDesdeUltimoAviso += SLEEP_TIME;
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public void addTerminaLogoDiaListener(TerminaLogoDia listener) {
		terminaLogoDiaListeners.add(listener);
	}
	
	@Override
	public void addTerminooouListener(Terminooou listener) {
		terminooouListeners.add(listener);
	}

}
